package gamelogic

import (
	"encoding/json"
	"errors"
	"google.golang.org/protobuf/proto"
	"gorm.io/gorm"
	"net"
	"os"
	"path/filepath"
	"server_cluster/common/config"
	"server_cluster/common/gdconf"
	"server_cluster/common/logger"
	"server_cluster/common/myepoll"
	"server_cluster/common/mysock"
	"server_cluster/common/protoc/pb"
	"server_cluster/common/tools"
	"server_cluster/logic/db"
	"server_cluster/logic/game_config"
	"server_cluster/logic/sharemem"
	"strconv"
)

type ReLoginKickReg struct {
	Uid          int64
	GateServerId int16
	Buf          *mysock.SockBuf
	IsGmUser     bool
}

var ReLoginKickRegMap = make(map[int64]*ReLoginKickReg)

var LocalEventChan = make(chan *LocalEvent, 1000)

const (
	LocalEventTypeReLoginKickFinish = iota
)

type LocalEvent struct {
	Type int
	Msg  any
}

func LocalEventHandle(localEvent *LocalEvent) {
	switch localEvent.Type {
	case LocalEventTypeReLoginKickFinish:
		defer func() {
			if err := recover(); err != nil {
				logger.Error("!!! LocalEventHandle PANIC !!!")
				logger.Error("error: %v", err)
				logger.Error("stack: %v", logger.Stack())
			}
			SELF = nil
		}()
		msg := localEvent.Msg.(*ReLoginKickReg)
		user, exist := sharemem.GetUserMap()[msg.Uid]
		if !exist {
			return
		}
		user.Shm_user.GateServerId = msg.GateServerId
		user.Shm_user.IsGmUser = msg.IsGmUser
		user.Shm_user.FreeNet = true
		user.Shm_user.UserDataInit()

		pbLevelChange := pb.User_Level_Change_Info{
			Level: int32(user.Shm_user.Level),
			Exp:   user.Shm_user.Exp,
		}
		OnLogin(user.Shm_user)
		pbLevelChange.LevelAfter = int32(user.Shm_user.Level)
		pbLevelChange.ExpAfter = user.Shm_user.Exp

		user.Shm_user.FreeNet = false

		SendLoginRsp(msg.Buf, user.Shm_user, config.SC_Login, config.OK, &pb.SC_Login{Timenow: sharemem.MyShm.TimeNow, Base: user.Shm_user.PackUserBaseAll()})
		//LoginNotify(msg.Buf, user.Shm_user)
		logger.Info("re-login ok, get user data from shm, uid: %v", user.Shm_user.GetUid())
	}
}

func SendLocal(_type int, msg any) {
	LocalEventChan <- &LocalEvent{
		Type: _type,
		Msg:  msg,
	}
}

func UserLogin(conn *myepoll.Conn, buf *mysock.SockBuf, shm_user **sharemem.User) int16 {
	req := new(pb.CS_Login)
	data := buf.Data[mysock.HEAD_LEN : mysock.HEAD_LEN+buf.Data_length]
	err := proto.Unmarshal(data, req)
	if err != nil {
		logger.Error("parse pb msg err: %v, addr: %v", err, conn.Socket.RemoteAddr().String())
		return config.PROTO_ERROR
	}
	logger.Debug("[RECV] cmdId: %v, cmdName: %v, msg: %v, uid: %v", config.CS_Login, req.ProtoReflect().Descriptor().FullName(), req, req.Uid)

	uid := req.GetUid()

	// 令牌验证

	// 本机查询缓存是否还在
	u, ok := sharemem.GetUserMap()[uid]
	if ok {
		if !u.Shm_user.CheckSelf(uid) {
			sharemem.DelUser(uid)
		} else {
			if u.Shm_user.IsOnline {
				// 顶登录
				logger.Info("do re-login kick, uid: %v", u.Shm_user.GetUid())
				ReLoginKickRegMap[u.Shm_user.GetUid()] = &ReLoginKickReg{
					Uid:          u.Shm_user.GetUid(),
					GateServerId: conn.Sid,
					Buf:          buf,
					//IsGmUser:     isUidWhiteList,
				}
				if u.Shm_user.GateServerId != conn.Sid {
					kickBuf := mysock.Create()
					kickBuf.Session = uint64(u.Shm_user.GetUid())
					kickBuf.Command = config.SC_Kick_User
					kickBuf.WriteToServer(myepoll.CONN_TYPE_GATE, u.Shm_user.GateServerId, nil)
				} else {
					Offline(u.Shm_user)
				}
				return config.OK
			}
			// 直接使用
			*shm_user = u.Shm_user
			logger.Info("login ok, get user data from shm, uid: %v", uid)
			(*shm_user).GateServerId = conn.Sid
			//(*shm_user).IsGmUser = isUidWhiteList
			(*shm_user).FreeNet = true
			(*shm_user).UserDataInit()
			pbLevelChange := pb.User_Level_Change_Info{
				Level: int32((*shm_user).Level),
				Exp:   (*shm_user).Exp,
			}
			OnLogin(*shm_user)
			pbLevelChange.LevelAfter = int32((*shm_user).Level)
			pbLevelChange.ExpAfter = (*shm_user).Exp

			(*shm_user).FreeNet = false
			SendLoginRspByConn(conn.Socket, buf, uint64(uid), config.SC_Login, config.OK, &pb.SC_Login{Timenow: sharemem.MyShm.TimeNow, Base: (*shm_user).PackUserBaseAll()})
			//LoginNotify(buf, *shm_user)
			return config.OK
		}
	}

	dbUser := db.DbUser{Id: uid}
	err = dbUser.GetByModel()
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		logger.Error("get user from db err: %v, uid: %v", err, uid)
		return SendLoginRspByConn(conn.Socket, buf, uint64(uid), config.SC_Login, config.SERVER_ERROR, nil)
	}
	if dbUser.Server > 0 && dbUser.Server != int16(game_config.GetConfig().ServerId) {
		// 已登录其它服务器
		logger.Error("login server id not match, user server id: %v, this server id: %v, uid: %v", dbUser.Server, game_config.GetConfig().ServerId, uid)
		return SendLoginRspByConn(conn.Socket, buf, uint64(uid), config.SC_Login, config.ALREADY_LOGIN, nil)
	}

	if *shm_user == nil {
		// new共享内存user
		*shm_user = sharemem.AllocUser(uid)
		if *shm_user == nil {
			return SendLoginRspByConn(conn.Socket, buf, uint64(uid), config.SC_Login, config.MAX_PLAYER, nil)
		}
		logger.Info("alloc shm user ok, index: %v, uid: %v", (*shm_user).Index, uid)
	}

	isNew := false
	if errors.Is(err, gorm.ErrRecordNotFound) {
		// 新注册账号
		isNew = true
		(*shm_user).Created = tools.TimeNow()
	} else {
		// 数据库用户数据载入到共享内存
		ret := DM_user(*shm_user, &dbUser)
		if ret != config.OK {
			logger.Error("parse user data from db ret: %v, uid: %v", ret, uid)
			SendLoginRsp(buf, *shm_user, config.SC_Login, config.LOGIN_INIT_FAIL, nil)
			(*shm_user).CleanUser()
		}
	}

	// 登录初始化
	logger.Info("login ok, load user data from db, uid: %v", uid)
	dbUser.UpdateServer(int16(game_config.GetConfig().ServerId))
	(*shm_user).GateServerId = conn.Sid
	//(*shm_user).IsGmUser = isUidWhiteList
	(*shm_user).FreeNet = true
	(*shm_user).UserDataInit()
	if isNew {
		var nickname string
		if !game_config.GetConfig().DevEnv {
			dbAccount, err := db.GetDbAccount(uint32(uid))
			if err != nil {
				logger.Error("get account from db err: %v, uid: %v", err, uid)
				return SendLoginRsp(buf, *shm_user, config.SC_Login, config.SERVER_ERROR, nil)
			}
			nickname = dbAccount.Nickname
		}
		logger.Info("reg new user, uid: %v", uid)
		Reg(nickname, *shm_user)
	}

	pbLevelChange := pb.User_Level_Change_Info{
		Level: int32((*shm_user).Level),
		Exp:   (*shm_user).Exp,
	}
	OnLogin(*shm_user)
	pbLevelChange.LevelAfter = int32((*shm_user).Level)
	pbLevelChange.ExpAfter = (*shm_user).Exp

	(*shm_user).FreeNet = false
	SendLoginRsp(buf, (*shm_user), config.SC_Login, config.OK, &pb.SC_Login{Timenow: sharemem.MyShm.TimeNow, Base: (*shm_user).PackUserBaseAll()})
	//LoginNotify(buf, *shm_user)
	return config.OK
}

func Offline(user *sharemem.User) int16 {
	uid := user.GetUid()
	kickUser := user.Kick
	clearUser := user.Clear
	user.OnOffline()
	if kickUser {
		SaveAndClearUser(user)
		logger.Warn("kick user ok, uid: %v", uid)
	}
	if clearUser {
		err := DeleteUser(uid)
		if err != nil {
			logger.Error("delete user from db error: %v, uid: %v", err, uid)
		}
		logger.Warn("clear user ok, uid: %v", uid)
	}
	msg, exist := ReLoginKickRegMap[uid]
	if exist {
		delete(ReLoginKickRegMap, uid)
		SendLocal(LocalEventTypeReLoginKickFinish, msg)
		logger.Info("do re-login kick ok, uid: %v", uid)
	}
	return config.OK
}

func Reconnect(user *sharemem.User, buf *mysock.SockBuf) int16 {
	logger.Info("user reconnect, uid: %v", user.GetUid())
	if user.GetUid() == 0 {
		return config.FAIL
	}
	// user.OnOffline()
	user.UserDataInit()

	pbLevelChange := pb.User_Level_Change_Info{
		Level: int32(user.Level),
		Exp:   user.Exp,
	}
	OnLogin(user)
	pbLevelChange.LevelAfter = int32(user.Level)
	pbLevelChange.ExpAfter = user.Exp

	SendMsg(config.SC_Reconnect, &pb.SC_Reconnect{Base: user.PackUserBaseAll()}, buf, user)
	//LoginNotify(buf, user)
	return config.OK
}

func OnTick(user *sharemem.User) {
	defer func() {
		if err := recover(); err != nil {
			logger.Error("!!! OnTick PANIC !!!")
			logger.Error("error: %v", err)
			logger.Error("stack: %v", logger.Stack())
		}
		SELF = nil
	}()
	// logger.Debug("[OnTick] uid: %v", u.GetUid())
	// 刷新每日任务
	RefreshDailyQuest(user)
	RefreshActivityDailyTask(user)
	RefreshActivityWeeklyTask(user)
	ExpireSignIn(user)
	RefreshActivitySignIn(user)
	RefreshDailyActivitySignIn(user)
	ExpireZpActivity(user)
	AcceptZpActivity(user)
	RefreshZpActivityTask(user)
	user.RefreshHomeFactory()
	AcceptTimerMail(user)
}

func OnLogin(user *sharemem.User) {
	logger.Info("user online, uid: %v", user.GetUid())
	user.IsOnline = true
	// 更新任务
	TriggerOpenState(user)
	AcceptQuest(user)
	// 更新场景
	for _, scene := range user.GetSceneMap() {
		scene.UpdateScene(user)
	}
	// 全服邮件
	user.AcceptGlobalMail()
	// 活动
	user.TriggerActivityTask(gdconf.ActivityTaskFinishCondLogin)
	TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_WEAPON_COUNT_BY_LEVEL, true)
	TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_EQUIP_COUNT_BY_LEVEL, true)
	UserLevelUp(user)
}

func CalcUserStatus() {
	activeUidList := make([]int64, 0)
	onlineUidList := make([]int64, 0)
	for _, user := range sharemem.GetUserMap() {
		activeUidList = append(activeUidList, user.Shm_user.GetUid())
		if user.Shm_user.IsOnline {
			onlineUidList = append(onlineUidList, user.Shm_user.GetUid())
		}
		//if !user.Shm_user.IsOnline && tools.TimeNow()-user.Shm_user.LastOfflineTime > int64(game_config.GetConfig().CleanTime) {
		//	SaveAndClearUser(user.Shm_user)
		//}
	}
	logger.Info("online user num: %v", len(onlineUidList))
	logger.Info("active user num: %v", len(activeUidList))
}

func SaveAndClearUser(user *sharemem.User) {
	// user数据写入数据库
	res := MD_User(user.Index, true)
	if res != nil {
		logger.Error("save user fail,error :%v, uid: %v", res, user.GetUid())
		return
	}
	// 清理user
	dbUser := db.DbUser{
		Id: user.Id.NewVal,
	}
	user.CleanUser()
	// 同步数据库server id标志
	dbUser.UpdateServer(0)
}

func DumpPlayerData(user *sharemem.User) {
	logger.Warn("start dump player, uid: %v", user.GetUid())
	data, err := json.Marshal(user)
	if err != nil {
		logger.Warn("dump player data json error: %v, uid: %v", err, user.GetUid())
		return
	}
	path := "./dump_player_data/user_" + strconv.Itoa(int(user.GetUid())) + ".json"

	logger.Warn("DumpPlayerData 1 path: %v", path)
	dir := filepath.Dir(path)
	if _, err = os.Stat(dir); os.IsNotExist(err) {
		if err = os.MkdirAll(dir, 0755); err != nil { // 0755 是目录权限
			logger.Warn("Error creating directory:", err)
			return
		}
	}

	logger.Warn("DumpPlayerData 2")
	err = os.WriteFile(path, data, 0644)
	if err != nil {
		logger.Warn("save player data file error: %v, uid: %v", err, user.GetUid())
		return
	}
	logger.Warn("dump player finish, uid: %v", user.GetUid())
}

func AcceptGlobalMailFromDb(user *sharemem.User) {
	mailConfigList, err := db.GetMailConfigWhereIdGt(user.GlobalMailId)
	if err != nil {
		logger.Error("get mail config err: %v, uid: %v", err, user.GetUid())
		return
	}
	for _, mailConfig := range mailConfigList {
		ok, _ := user.AddMail(mailConfig.Title, mailConfig.Content, mailConfig.Sender, mailConfig.ExpireTime, true, mailConfig.ItemMap)
		if !ok {
			logger.Error("add global server mail fail, uid: %v", user.GetUid())
			continue
		}
		// 刷新当前id
		user.GlobalMailId = mailConfig.Id
	}
}

func Reg(nickname string, user *sharemem.User) int32 {
	if nickname == "" {
		nickname = "玩家" + strconv.Itoa(int(user.GetUid()))
	}
	user.SetName(nickname)
	user.SetLevel(1)
	// 添加角色
	initRoleId := gdconf.GetConstIntList("DEFAULTROLE")
	for _, roleId := range initRoleId {
		if roleId == 0 {
			continue
		}
		ok := AddRole(roleId, user)
		if !ok {
			logger.Error("add role fail, initRoleId: %v", initRoleId)
			return config.SERVER_ERROR
		}
		UnlockCodex(pb.CodexType_CODEX_ROLE, roleId, user)
	}
	// 添加场景
	initSceneId := int32(gdconf.GetConstInt("DEFAULTSCENE"))
	user.SetSceneId(initSceneId)
	ok := user.AddScene(initSceneId)
	if !ok {
		logger.Error("add scene fail, initSceneId: %v", initSceneId)
		return config.SERVER_ERROR
	}
	user.SetCurrCollCount(int32(gdconf.GetConstInt("AVSMAXCOLLISIONS")))
	// TODO 解锁全部家园建筑
	for buildingId := range gdconf.GetHomeBuildingConfigMap() {
		user.AddUnlockBuilding(buildingId)
	}
	// 队伍
	user.InitTeam(initRoleId)
	user.UserActivity.SetTowerArea(1)
	user.UserActivity.SetCaptainRoleId(int32(gdconf.GetConstInt("DEFAULTCAPTAIN")))
	AcceptQuest(user)
	user.SetSync()
	user.UserHome.OnUserReg()
	return config.OK
}

func ChangeUserRes(id int32, num int32, user *sharemem.User) {
	switch id {
	case gdconf.ITEM_EXP:
		AddExp(user, num)
		TriggerOpenState(user)
		AcceptQuest(user)
	case gdconf.ITEM_GEM:
		user.AddGem(num)
	case gdconf.ITEM_GOLD:
		user.AddGold(num)
	default:
	}
	user.SetSync()
}

func ParseMsg(cmdId uint32, msg proto.Message, Buf *mysock.SockBuf, user *sharemem.User) proto.Message {
	if Buf == nil {
		logger.Debug("[IGNORE SEND MSG] cmdId: %v, cmdName: %v, msg: %v, uid: %v", cmdId, msg.ProtoReflect().Descriptor().FullName(), msg, user.GetUid())
		return nil
	}
	data := Buf.Data[mysock.HEAD_LEN : mysock.HEAD_LEN+Buf.Data_length]
	err := proto.Unmarshal(data, msg)
	if err != nil {
		logger.Error("parse pb msg err: %v, uid: %v", err, user.GetUid())
		return nil
	}
	if cmdId != config.CSC_Heart {
		logger.LOG.EnableJson = true
		logger.Debug("[RECV] cmdId: %v, cmdName: %v, msg: %v, uid: %v", cmdId, msg.ProtoReflect().Descriptor().FullName(), msg, user.GetUid())
		logger.LOG.EnableJson = false
	}
	return msg
}

func SendMsg(cmdId uint32, msg proto.Message, Buf *mysock.SockBuf, user *sharemem.User) int16 {
	if user.FreeNet {
		return config.OK
	}
	if Buf == nil {
		Buf = mysock.Create()
		Buf.Session = uint64(user.GetUid())
	}
	Buf.Command = cmdId
	Buf.Code = config.OK
	data, err := proto.Marshal(msg)
	if err != nil {
		logger.Error("build pb msg err: %v, uid: %v", err, user.GetUid())
		return config.PROTO_ERROR
	}
	if cmdId != config.CSC_Heart {
		logger.LOG.EnableJson = true
		logger.Debug("[SEND] cmdId: %v, cmdName: %v, msg: %v, uid: %v", cmdId, msg.ProtoReflect().Descriptor().FullName(), msg, user.GetUid())
		logger.LOG.EnableJson = false
	}
	Buf.WriteToServer(myepoll.CONN_TYPE_GATE, user.GateServerId, data)
	return config.OK
}

func SendLoginRsp(buf *mysock.SockBuf, user *sharemem.User, cmdId uint32, retCode int32, msg proto.Message) int16 {
	buf.Command = cmdId
	buf.Session = uint64(user.GetUid())
	buf.Code = uint16(retCode)
	data, err := proto.Marshal(msg)
	if err != nil {
		logger.Error("build pb msg err: %v, uid: %v", err, user.GetUid())
		return config.PROTO_ERROR
	}
	logger.LOG.EnableJson = true
	logger.Debug("[SEND] cmdId: %v, cmdName: %v, msg: %v, uid: %v", cmdId, msg.ProtoReflect().Descriptor().FullName(), msg, user.GetUid())
	logger.LOG.EnableJson = false
	buf.WriteToServer(myepoll.CONN_TYPE_GATE, user.GateServerId, data)
	return config.OK
}

func SendLoginRspByConn(conn net.Conn, buf *mysock.SockBuf, uid uint64, cmdId uint32, retCode int32, msg proto.Message) int16 {
	buf.Command = cmdId
	buf.Session = uid
	buf.Code = uint16(retCode)
	data, err := proto.Marshal(msg)
	if err != nil {
		logger.Error("build pb msg err: %v, uid: %v", err, uid)
		return config.PROTO_ERROR
	}
	logger.LOG.EnableJson = true
	logger.Debug("[SEND] cmdId: %v, cmdName: %v, msg: %v, uid: %v", cmdId, msg.ProtoReflect().Descriptor().FullName(), msg, uid)
	logger.LOG.EnableJson = false
	return int16(buf.WriteToByConn(conn, data))
}

// =========协议消息处理======

func UserLogout(user *sharemem.User, buf *mysock.SockBuf) int16 {
	// 获取前端数据
	req, ok := ParseMsg(config.CS_Logout, new(pb.CS_Logout), buf, user).(*pb.CS_Logout)
	if !ok {
		return config.PROTO_ERROR
	}
	_ = req
	user.OnOffline()
	return SendMsg(config.SC_Logout, &pb.SC_Logout{}, buf, user)
}
func LoginNotify(buf *mysock.SockBuf, user *sharemem.User) {
	// 登录通知包
	SendMsg(config.SC_OpenFuncNtf, &pb.SC_OpenFuncNtf{FuncIdList: user.UserQuest.GetOpenState()}, buf, user)
	SendMsg(config.SC_CodexDataFullNotify, &pb.SC_CodexDataFullNotify{TypeDataList: user.PacketCodexAllTypeData(nil)}, buf, user)
	SendMsg(config.SC_CaptainSkillDataNtf, user.PacketUserRoleCaptainSkillData(), buf, user)
	SendMsg(config.SC_SceneDashUpdateNtf, &pb.SC_SceneDashUpdateNtf{CurrCollCount: int64(user.UserScene.CurrCollCount)}, buf, user)
}

func UserFetch(user *sharemem.User, buf *mysock.SockBuf) int16 {
	// 获取前端数据
	req, ok := ParseMsg(config.CS_FETCH, new(pb.CS_Fetch), buf, user).(*pb.CS_Fetch)
	if !ok {
		return config.PROTO_ERROR
	}

	unlockSceneIdList := make([]int32, 0)
	for _, scene := range user.GetSceneMap() {
		unlockSceneIdList = append(unlockSceneIdList, scene.SceneId)
	}
	rsp := &pb.SC_Fetch{
		Status:            config.OK,
		Type:              req.Type,
		UnlockSceneIdList: unlockSceneIdList,
	}
	switch req.Type {
	case config.Fetch_type_all:
		rsp.Base = user.PackUserBaseAll()
		user.PackUserItemAll(rsp)
		user.PackUserRoleAll(rsp)
		user.PacketUserQuestAll(rsp)
		user.PackUserClientData(rsp)
		user.PacketUserEquipAll(rsp)
		user.PacketUserTeamAll(rsp)
		user.PackUserWeaponAll(rsp)
	case config.Fetch_type_base:
		rsp.Base = user.PackUserBaseAll()
	case config.Fetch_type_item:
		user.PackUserItemAll(rsp)
	case config.Fetch_type_role:
		user.PackUserRoleAll(rsp)
	case config.Fetch_type_scene: //数据太多 完全弃用
	case config.Fetch_type_task:
		user.PacketUserQuestAll(rsp)
	case config.Fetch_type_client:
		user.PackUserClientData(rsp)
	case config.Fetch_type_equip:
		user.PacketUserEquipAll(rsp)
	case config.Fetch_type_team:
		user.PacketUserTeamAll(rsp)
	case config.Fetch_type_weapon:
		user.PackUserWeaponAll(rsp)
	default:
	}
	SendMsg(config.SC_FETCH, rsp, buf, user)
	return config.OK
}

func SetClientDataReq(user *sharemem.User, buf *mysock.SockBuf) int16 {
	req, ok := ParseMsg(config.CS_SetClientDataReq, new(pb.CS_SetClientDataReq), buf, user).(*pb.CS_SetClientDataReq)
	if !ok {
		return config.PROTO_ERROR
	}

	user.SetClientData(req.ClientData)

	return SendMsg(config.SC_SetClientDataRsp, &pb.SC_SetClientDataRsp{RetCode: config.OK}, buf, user)
}

func OnDayChange(user *sharemem.User, buf *mysock.SockBuf) int16 {
	var pbData = pb.SC_OnDayChangeRsp{
		LevelChange: &pb.User_Level_Change_Info{},
	}
	pbData.LevelChange.Level = int32(user.Level)
	pbData.LevelChange.Exp = user.Exp
	UserLevelUp(user)
	pbData.LevelChange.LevelAfter = int32(user.Level)
	pbData.LevelChange.ExpAfter = user.Exp
	return SendMsg(config.SC_OnDayChangeRsp, &pbData, buf, user)
}

func SaveAllUser() {
	for i := 0; i < game_config.USER_MAX; i++ {
		if sharemem.MyShm.Usr[i].Id.NewVal == 0 {
			// 索引空数据
			continue
		}
		res := MD_User(int32(i), true)
		if res != nil {
			// 保存失败
			user := &(sharemem.MyShm.Usr[i])
			logger.Error("save user fail,error :%v, uid: %v", res, user.GetUid())
			//DumpPlayerData(user)
		}
	}
}

func AddExp(user *sharemem.User, exp int32) {
	user.Exp += exp
	// 玩家升级
	UserLevelUp(user)
}
func UserLevelUp(user *sharemem.User) {
	var openDay = sharemem.GetServerOpen2NowDay()
	for {
		// 读取玩家等级配置表
		playerLevelConfig := gdconf.GetPlayerLevelConfig(int32(user.Level))
		if playerLevelConfig == nil {
			// 获取不到代表已经到达最大等级
			break
		}
		var nextLevelConfig = gdconf.GetPlayerLevelConfig(int32(user.Level + 1))
		// 确保拥有下一级的配置表
		if nextLevelConfig == nil {
			// 获取不到代表已经到达最大等级
			break
		}
		if openDay != -1 && nextLevelConfig.SeverDay > openDay {
			break
		}
		// 玩家冒险阅历不足则跳出循环
		if user.Exp < playerLevelConfig.Exp {
			break
		}
		// 玩家增加冒险等阶
		user.Level++
		user.Exp -= playerLevelConfig.Exp
	}
	TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_PLAYER_LEVEL, true)
}
